using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace TankWars
{
    public class TankTurret : MovableSprite
    {
        //This variable effects how fast the turrent turns;
        private const float turnSpeed = 5.0f;

        private Tank tank;
        private Vector2 vOffset = Vector2.Zero;
        private float angVelocity = 0;

        /// <summary>
        /// Gets the origin of the turret that it should rotate on
        /// </summary>
        private new Vector2 Origin
        {
            get
            {
                return new Vector2(base.SpriteWidth * .225f, base.SpriteHeight/2);
            }
        }

        /// <summary>
        /// Gets the position vector at the end of the tank turret
        /// </summary>
        public Vector2 EndOfTurret
        {
            get
            {
                //The base of the turrent starts at the tank's coordinates.
                Vector2 vEndOfTurret = this.tank.vPosition;

                //Turrent length is going to be equal to the width of the sprite minus the origin.
                float turrentLength = base.SpriteWidth - Origin.X;

                vEndOfTurret.X += turrentLength * (float)Math.Cos(base.fRotation);
                vEndOfTurret.Y += turrentLength * (float)Math.Sin(base.fRotation);

                return vEndOfTurret;
            }
        }

        public TankTurret(Texture2D turretTexture, Tank owningTank)
            : base(turretTexture)
        {
            this.tank = owningTank;
        }

        public TankTurret(Texture2D turretTexture, Tank owningTank, Vector2 vTurretOffset)
            : base(turretTexture)
        {
            this.tank = owningTank;
            vPosition =
            this.vOffset = vTurretOffset;
        }

        public TankTurret(Texture2D turretTexture, Tank owningTank, string strSpriteName, string strFrameXMLFile) 
            : base(strSpriteName, turretTexture,strFrameXMLFile)
        {
            this.tank = owningTank;
        }

        public TankTurret(Texture2D turretTexture, Tank owningTank, Vector2 vTurretOffset, string strSpriteName, string strFrameXMLFile) 
            : base(strSpriteName, turretTexture,strFrameXMLFile)
        {
            this.tank = owningTank;
            vPosition = 
            this.vOffset = vTurretOffset;
        }

        /// <summary>
        /// Draws the tank turret at the origin of the tank, pointing towards the mouse
        /// </summary>
        /// <param name="spriteBatch"></param>
        /// <param name="mouseState"></param>
        public new void Draw(SpriteBatch spriteBatch, Map map)
        {
            //spriteBatch.Draw(base.Sprite, map.GetTrueScreenPosition(this.tank.vPosition), null, this.tank.TankColor, base.fRotation, this.Origin, 1.0f, SpriteEffects.None, 0.0f);
            base.Draw(spriteBatch, map.GetTrueScreenPosition(this.tank.vPosition), base.fRotation, this.Origin, this.tank.TankColor);
        }

        /// <summary>
        /// Updates the rotation of the turret
        /// </summary>
        /// <param name="mouseState"></param>
        public void UpdatePosition(MouseState mouseState, Map map, GameTime gameTime)
        {
            //Update the velocity according to the mouse position.
            this.UpdateTurrentVelocity(this.GetMouseRotation(mouseState, map));

            //Update the turrent's angle based on the velocity.
            base.fRotation += this.angVelocity * (float)gameTime.ElapsedGameTime.TotalSeconds;

            //Reset the rotation if it goes out of bounds.
            if (base.fRotation < 0)
                base.fRotation += MathHelper.ToRadians(360);
            else if (base.fRotation > MathHelper.ToRadians(360))
                base.fRotation -= MathHelper.ToRadians(360);
        }

        /// <summary>
        /// Returns the angle the mouse is at compared to the tank
        /// </summary>
        /// <param name="mouseState"></param>
        /// <returns></returns>
        private float GetMouseRotation(MouseState mouseState, Map map)
        {
            //Get the mouse coordinates
            float fMouseX = mouseState.X;
            float fMouseY = mouseState.Y;

            float fTankX = map.GetTrueScreenPosition(this.tank.vPosition).X;
            float fTankY = map.GetTrueScreenPosition(this.tank.vPosition).Y;

            //Use arc tangent to get the angle.
            float fRotation = (float)Math.Atan2(fTankY - fMouseY, fMouseX - fTankX);

            //Ensure that the angle is in the proper quadrant based
            //on the given coordinates of the mouse and the tank

            //First Quadrant
            if ((fMouseX >= fTankX) && (fMouseY <= fTankY))
            {
                while ((MathHelper.ToDegrees(fRotation) > 90) || (MathHelper.ToDegrees(fRotation) < 0))
                {
                    fRotation += MathHelper.ToRadians(180);
                    if (fRotation > MathHelper.ToRadians(360))
                    {
                        fRotation -= MathHelper.ToRadians(360);
                    }
                }
            }
            //Second Quadrant
            else if ((fMouseX <= fTankX) && (fMouseY <= fTankY))
            {
                while ((fRotation > MathHelper.ToRadians(180)) || (fRotation < MathHelper.ToRadians(90)))
                {
                    fRotation += MathHelper.ToRadians(180);
                    if (fRotation > MathHelper.ToRadians(360))
                    {
                        fRotation -= MathHelper.ToRadians(360);
                    }
                }
            }
            //Third Quadrant
            else if ((fMouseX <= fTankX) && (fMouseY >= fTankY))
            {
                while ((fRotation > MathHelper.ToRadians(270)) || (fRotation < MathHelper.ToRadians(180)))
                {
                    fRotation += MathHelper.ToRadians(180);
                    if (fRotation > MathHelper.ToRadians(360))
                    {
                        fRotation -= MathHelper.ToRadians(360);
                    }
                }
            }
            //Fourth Quadrant
            else
            {
                while ((fRotation > MathHelper.ToRadians(360)) || (fRotation < MathHelper.ToRadians(270)))
                {
                    fRotation += MathHelper.ToRadians(180);
                    if (fRotation > MathHelper.ToRadians(360))
                        fRotation -= MathHelper.ToRadians(360);
                }
            }

            fRotation = MathHelper.ToRadians(360) - fRotation;
            return fRotation;
        }//Get MouseAngle Method

        private void UpdateTurrentVelocity(float mouseAngle)
        {
            //Get the difference between the mouse angle and the turrent angle.
            float difference = mouseAngle - base.fRotation;

            //If positive
            if (difference >= 0)
            {
                angVelocity = turnSpeed;
            }
            else//If negative
            {
                //Make difference positive;
                difference *= -1;
                angVelocity = (-1) * turnSpeed;
            }

            //If difference is greater than 180 than the turrent should turn the opposite way.
            if (difference > MathHelper.ToRadians(180))
            {
                //Since the turrent is turning the other way, the difference angle changes.
                difference = MathHelper.ToRadians(360) - difference;

                //Change velocity direction.
                angVelocity *= (-1);
            }

            //Slow speed of turrent as it approaches its destination.
            angVelocity *= (float)(0.5 + difference/MathHelper.ToRadians(180));

            //Stop turrent if it is within one degree of position.
            if (difference < MathHelper.ToRadians(1))
                angVelocity = 0;

        }//UpdateTurrentVelocity Method

    }
}
